package net.ib.mtalk.ui.chat;

import java.util.ArrayList;
import java.util.UUID;

import net.ib.mntalk.protocol.Common;
import net.ib.mntalk.protocol.Common.Message;
import net.ib.mntalk.protocol.Common.UUIDMsg;
import net.ib.mntalk.protocol.Common.UserBasicInfo;
import net.ib.mntalk.protocol.Common.UserMessage;
import net.ib.mntalk.protocol.Session.AddMembersReq;
import net.ib.mntalk.protocol.Session.SendMessageReq;
import net.ib.mtalk.R;
import net.ib.mtalk.base.BaseFragmentActivity;
import net.ib.mtalk.constant.HandlerMsgConst;
import net.ib.mtalk.database.DatabaseContract.MessageTable.MessageProperty;
import net.ib.mtalk.database.DatabaseContract.ViewTable;
import net.ib.mtalk.database.helper.InboxDatabaseHelper;
import net.ib.mtalk.database.task.DBInsertSendMessage;
import net.ib.mtalk.global.GlobalPreferences;
import net.ib.mtalk.ui.attachment.emoticon.EmoticonIme;
import net.ib.mtalk.ui.attachment.geotag.GeotagActivity;
import net.ib.mtalk.ui.attachment.scribble.ScribbleActivity;
import net.ib.mtalk.ui.attachment.sound.AudioRecordActivity;
import net.ib.mtalk.ui.attachment.vcalendar.VCalendarListActivity;
import net.ib.mtalk.ui.attachment.vcard.VCardListActivity;
import net.ib.mtalk.ui.buddy.item.BuddyUUIDItem;
import net.ib.mtalk.ui.dialog.DialogListItem;
import net.ib.mtalk.ui.dialog.DialogMenu;
import net.ib.mtalk.ui.dialog.DialogMenuOnClickListener;
import net.ib.mtalk.ui.fragment.ChatListFragment;
import net.ib.mtalk.util.Dip;
import net.ib.mtalk.util.GpbSupport;
import net.ib.mtalk.util.MTalkLogWriter;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.speech.RecognizerIntent;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.Toast;

public class ChatListActivity extends BaseFragmentActivity implements DialogMenuOnClickListener{

	public static final int MENU_ATTACHMENT_IMAGE		= Menu.FIRST + 30;
	public static final int MENU_ATTACHMENT_VIDEO		= Menu.FIRST + 31;
	public static final int MENU_ATTACHMENT_SCRIBBLE	= Menu.FIRST + 32;
	public static final int MENU_ATTACHMENT_GEOTAG		= Menu.FIRST + 33;
	public static final int MENU_ATTACHMENT_CONTACT		= Menu.FIRST + 34;
	public static final int MENU_ATTACHMENT_SCHEDULE	= Menu.FIRST + 35;
	public static final int MENU_ATTACHMENT_VOICE	 	= Menu.FIRST + 36;
	public static final int MENU_ATTACHMENT_GIFT		= Menu.FIRST + 37;
	
	public static final int GET_MESSAGE_MAX_COUNT = 20;
	public static final int GET_MESSAGE_COUNT = 10;
	public static final int GET_MEMBER_COUNT = 50;

	public static final String INTENT_CLIENT_VIEW_MSB 	= "intent_client_view_msb";
	public static final String INTENT_CLIENT_VIEW_LSB 	= "intent_client_view_lsb";
	public static final String INTENT_EXIST_VIEW 		= "intent_exist_view";
	public static final String INTENT_ENABLE 			= "intent_enable";	
	public static final String INVITE_PERSON 			= "invite_person";	

	public final static int MENU_INPUT_VOICE		= 101;
	public final static int MENU_ADD_MEMBER 		= 102;
	public final static int MENU_ATTACHMENT		= 103;
	public final static int MENU_SEND_EMAIL			= 104;

	public final static int REQ_IMAGE_EDIT 		= 0;
	public final static int REQ_IMAGE_ALBUM 	= 1;
	public final static int REQ_VIDEO_EDIT 		= 2;
	public final static int REQ_VIDEO_ALBUM 	= 3;
	public final static int REQ_SCRIBBLE 		= 4;
	public final static int REQ_GEOTAG 			= 5;
	public final static int REQ_VCARD 			= 6;
	public final static int REQ_VCALENDAR 		= 7;
	public final static int REQ_VOICE 			= 8;
	public final static int REQ_GIFT 			= 9;
	public final static int REQ_ADDMEMBER		= 10;
	public final static int REQ_CODE_VOICE_RECOGNITION = 21;

	// 뷰의 UUID 를 확인하기 위한 변수.
	public long mClientViewUuidMsb;
	public long mClientViewUuidLsb;
	private UUIDMsg mViewUuidMsg;
	
	private Context mContext;

	// FLAG 설정
	// 메시지를 하나라도 들고 있는 뷰인가?
	public boolean mExistFlag;
	// 뷰가 서버에 만들어졌는지 확인하기 위한 변수. 만들어져 있지 않다면 CreateView를 호출하기 위함.
	public int mEnable;
	
	private boolean newIntent;
	private Bundle mSavedInstanceState;

	private ChatController mUiController;

	private EditText editText;
	private Button sendBtn;
	private ImageView bgImage;

	TextWatcher watcher;
	
	private PopupWindow emoticonPopupWindow;

	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(android.os.Message msg) {
			switch(msg.what) {
			case HandlerMsgConst.HANDLER_CREATE_VIEW_SUCCESS :
				// TODO AFTER NET-WORK, RELOAD UI, adapter.notifyChanged()
				Toast.makeText(ChatListActivity.this, "HANDLER_CREATE_VIEW_SUCCESS", Toast.LENGTH_SHORT).show();
				break;
			case HandlerMsgConst.HANDLER_CREATE_VIEW_FAIL :
				// TODO AFTER NET-WORK, RELOAD UI, adapter.notifyChanged()
				Toast.makeText(ChatListActivity.this, "HANDLER_CREATE_VIEW_FAIL", Toast.LENGTH_SHORT).show();
				break;
			case HandlerMsgConst.HANDLER_UNKNOWN_ERROR :
				Toast.makeText(ChatListActivity.this, "HANDLER_UNKNOWN_ERROR", Toast.LENGTH_SHORT).show();
				// TODO AFTER NET-WORK, RELOAD UI, adapter.notifyChanged()
				break;
			case HandlerMsgConst.HANDLER_SEND_MESSAGE_SUCCESS :
				// 뷰가 정상적으로 만들어졌다!! subscribe를 걸고 FLAG값을 바꾸자!
				if(mEnable == ViewTable.EnableType.DISABLE.ordinal()){
					mEnable = ViewTable.EnableType.ENABLE.ordinal();
					mUiController.onSubscribe(mClientViewUuidMsb, mClientViewUuidLsb);
					mUiController.getMessages(mClientViewUuidMsb, mClientViewUuidLsb);
				}
				Toast.makeText(ChatListActivity.this, "HANDLER_SEND_MESSAGE_SUCCESS", Toast.LENGTH_SHORT).show();
				// TODO AFTER NET-WORK, RELOAD UI, adapter.notifyChanged()
				break;
			case HandlerMsgConst.HANDLER_SEND_MESSAGE_FAIL :
				Toast.makeText(ChatListActivity.this, "HANDLER_SEND_MESSAGE_FAIL", Toast.LENGTH_SHORT).show();
				// TODO AFTER NET-WORK, RELOAD UI, adapter.notifyChanged()
				break;
			case HandlerMsgConst.HANDLER_FILE_DOWNLOAD_START:
				mUiController.downloadFile((Message)msg.obj);
				break;
			default:
				break;
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_chat_list);
		newIntent = false;
		
		mSavedInstanceState = savedInstanceState;
		
		mContext = this;
		
		bgImage = (ImageView)findViewById(R.id.chatBgImage);
		
//		setBackGround(Configuration.ORIENTATION_PORTRAIT);

		watcher = new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				if(s == null || s.toString().equals("")){
					sendBtn.setBackgroundResource(R.drawable.btn_default_small_lightgrey_);
					sendBtn.setClickable(false);
				}else{
					if(mEnable != ViewTable.EnableType.LEAVE.ordinal()){
						sendBtn.setClickable(true);
						sendBtn.setBackgroundResource(R.drawable.btn_default_small_blue_);
					}
				}
			}
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,	int after) {	
			}
			@Override
			public void afterTextChanged(Editable s) {
				if(s == null || s.toString().equals("")){
					sendBtn.setBackgroundResource(R.drawable.btn_default_small_lightgrey_);
					sendBtn.setClickable(false);
				}else{
					if(mEnable != ViewTable.EnableType.LEAVE.ordinal()){
						sendBtn.setClickable(true);
						sendBtn.setBackgroundResource(R.drawable.btn_default_small_blue_);
					}
				}
			}
		};
		
		editText = (EditText) findViewById(R.id.editChatMsg);
		sendBtn = (Button) findViewById(R.id.btnChatSend);
		editText.addTextChangedListener(watcher);
		setInputSuggestions(getResources().getConfiguration().orientation);
		

		// GET EXTRAS
		final Bundle extras = getIntent().getExtras();
		if(extras == null){
			finish();
		}
		initializeView(extras);
	}
	/*public void onBackPressed()
	{
		finish();
		overridePendingTransition(R.anim.slide_bottom_in, R.anim.slide_bottom_out);
	}*/
	
	@Override
	protected void onNewIntent(Intent intent) {
		super.onNewIntent(intent);
		setIntent(intent);

		// GET EXTRAS
		final Bundle extras = getIntent().getExtras();
		if(extras == null){
			finish();
		}
		newIntent = true;
		initializeView(extras);
	}
	
	public void onConfigurationChanged(Configuration newConfig) {
		setInputSuggestions(newConfig.orientation);
		//setBackGround(newConfig.orientation);
		
		/*if (emoticonPopupWindow != null && emoticonPopupWindow.isShowing()) {
			emoticonPopupWindow.dismiss();
			return;
		}*/
		
		super.onConfigurationChanged(newConfig);
	}
	

	@Override
	public void onResume() {
		super.onResume();
		
		if(GlobalPreferences.getFixOrientation(this))
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		else
			setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
		
		editText.addTextChangedListener(watcher);
		if (mActivityResult != null) {
			handleActivityResult(mActivityResult.requestCode, mActivityResult.resultCode, mActivityResult.intent);
			mActivityResult = null;	// 반드시 있어야 함
		}
		if(mEnable != ViewTable.EnableType.DISABLE.ordinal()){
			mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.getMembers(mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.getMessages(mClientViewUuidMsb, mClientViewUuidLsb);
			if(mEnable == ViewTable.EnableType.ENABLE.ordinal()){
				mUiController.onSubscribe(mClientViewUuidMsb, mClientViewUuidLsb);
				GlobalPreferences.subscribeView = mViewUuidMsg;
			}			
		}
		Log.i("ATOM", "onResume");
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		Log.i("ATOM", "onPause");
		editText.removeTextChangedListener(watcher);
		
		if(mEnable == ViewTable.EnableType.ENABLE.ordinal()){
			mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.onUnsubscribe(mClientViewUuidMsb, mClientViewUuidLsb);
			GlobalPreferences.subscribeView = null;
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
//		if(mEnable == ViewTable.EnableType.ENABLE.ordinal()){
//			mUiController.onUnsubscribe(mClientViewMsb, mClientViewLsb);
//		}
		if(!mExistFlag){
			mUiController.checkDeleteView(mClientViewUuidMsb, mClientViewUuidLsb);
		}
	}

	@Override
	public void onLowMemory() {
		super.onLowMemory();

		// 메모리 부족하면 이모티콘 입력기를 닫아보자.
		if (emoticonPopupWindow != null && emoticonPopupWindow.isShowing()) {
			emoticonPopupWindow.dismiss();
		}
		emoticonPopupWindow = null;

		System.gc();
	}

	private void initializeView(Bundle extras){
		
		mEnable = extras.getInt(INTENT_ENABLE);
		mExistFlag = extras.getBoolean(INTENT_EXIST_VIEW);
		mClientViewUuidMsb = extras.getLong(INTENT_CLIENT_VIEW_MSB);
		mClientViewUuidLsb = extras.getLong(INTENT_CLIENT_VIEW_LSB);

		mUiController = new ChatController(this, mHandler, new UUID(mClientViewUuidMsb, mClientViewUuidLsb));

		MTalkLogWriter.d("ChatList : " + mClientViewUuidMsb + ", " + mClientViewUuidLsb);
		// LIST FRAGMENT
		FragmentManager fm = getSupportFragmentManager();

		ChatListFragment list = new ChatListFragment();
		if(mSavedInstanceState == null || newIntent) {
			if(newIntent){
				fm.beginTransaction().replace(R.id.lLayoutChat, list).commit();
			}else{
				list.setArguments(mSavedInstanceState);
				fm.beginTransaction().add(R.id.lLayoutChat, list).commit();
			}
			newIntent = false;
		}

		// CALL TO SERVER, GET-MESSAGES
		//mUiController.getMessages(mViewMsb, mViewLsb);
	}

	/**
	 * SEND BUTTON
	 * 
	 * @param view
	 */
	public void onSend(View view) {
		MTalkLogWriter.d(this.getClass().getName()+ ":onSend()");

		mExistFlag = true;

		UserMessage userMessage = new UserMessage();
		userMessage.setContentType(Common.CONTENT_TYPE_PLAIN); // ContentType enum
		userMessage.setContent(editText.getText().toString());
		userMessage.setSenderUuid(GlobalPreferences.getUserUUID());
		userMessage.setSenderName(GlobalPreferences.getUserName());

		SendMessageReq sendMessageReq = new SendMessageReq();
		sendMessageReq.setMessage(userMessage);
		mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
		sendMessageReq.setViewUuid(mViewUuidMsg);
		
		UUID clientMsgUuid = UUID.randomUUID();
		try{			
			DBInsertSendMessage task = new DBInsertSendMessage(this, mHandler, mClientViewUuidMsb, mClientViewUuidLsb, sendMessageReq, clientMsgUuid);
			task.execute();
		}catch(Exception e){
			MTalkLogWriter.e(e);
		}

		mUiController.sendMessage(sendMessageReq, mClientViewUuidMsb, mClientViewUuidLsb, clientMsgUuid);
		editText.setText("");
	}

	/**
	 * 사용자가 이모티콘 입력기를 띄우는 동작을 했을 때 이 함수가 호출된다.
	 * @param view 이 함수에 대한 호출자의 레퍼런스
	 */
	public void onEmoticonClick(View view){
		if (emoticonPopupWindow == null) {
			emoticonPopupWindow = new EmoticonIme()
			.create(ChatListActivity.this, (int) Dip.toPixel(320), (int) Dip.toPixel(215), editText);
		}
		if (emoticonPopupWindow.isShowing()) {
			emoticonPopupWindow.dismiss();
		} else {
			emoticonPopupWindow.showAtLocation(findViewById(R.id.chatBgImage),//lLayoutChat),
					Gravity.CENTER_HORIZONTAL|Gravity.TOP, 0, (int) Dip.toPixel(25));
		}
	}

	public void showDialogMenu(){
		if(mEnable != ViewTable.EnableType.LEAVE.ordinal()){
			DialogMenu dialogMenu = new DialogMenu(this, getMenuList());
			dialogMenu.createDialog().show();
		}
	}
	
	@Override
	public boolean onClickDailogMenu(Object obj, int tag){
		switch(tag){
			case MENU_ATTACHMENT_IMAGE:
				MTalkLogWriter.d("MENU : ATTACHMENT_IMAGE");
				
				String newImage = this.getResources().getString(R.string.attachment_image_new);
				String albumImage = this.getResources().getString(R.string.attachment_image_album);
				String[] imageMenus = new String[]{newImage, albumImage};

				new AlertDialog.Builder(ChatListActivity.this)
				.setTitle(R.string.attachment_image_name)
				.setItems(imageMenus, new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						switch (which) {
						case 0:	// new
							requestCamera();
							break;
						case 1:	// album
							// 안드로이드 갤러리에 이미지들을 요청
							Intent photoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
							photoPickerIntent.setType("image/*");
							startActivityForResult(photoPickerIntent, REQ_IMAGE_ALBUM);
							break;
						}
					}
				}).show();
				break;
			case MENU_ATTACHMENT_VIDEO:
				MTalkLogWriter.d("MENU : ATTACHMENT_VIDEO");
				mExistFlag = true;
				
				String newVideo = this.getResources().getString(R.string.attachment_video_new);
				String albumVideo = this.getResources().getString(R.string.attachment_video_album);
				String[] videoMenus = new String[]{newVideo, albumVideo};
				
				new AlertDialog.Builder(ChatListActivity.this)
				.setTitle(R.string.attachment_video_name)
				.setItems(videoMenus, new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						switch (which) {
						case 0:	// new
							requestVideoRecord();
							break;
						case 1:	// album
							// 안드로이드 갤러리에 동영상들을 요청
							Intent videoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
							videoPickerIntent.setType("video/*");
							startActivityForResult(Intent.createChooser(videoPickerIntent, "Select Video Source..."), REQ_VIDEO_ALBUM);
							break;
						}
					}
				}).show();
				break;
			case MENU_ATTACHMENT_SCRIBBLE:
				MTalkLogWriter.d("MENU : ATTACHMENT_SCRIBBLE");
				Intent scribbleIntent = new Intent(ChatListActivity.this, ScribbleActivity.class);
				startActivityForResult(scribbleIntent, REQ_SCRIBBLE);
				break;
			case MENU_ATTACHMENT_GEOTAG:
				MTalkLogWriter.d("MENU : ATTACHMENT_GEOTAG");
				Intent geotagIntent = new Intent(ChatListActivity.this, GeotagActivity.class);
				startActivityForResult(geotagIntent, REQ_GEOTAG);
				break;
			case MENU_ATTACHMENT_CONTACT:
				MTalkLogWriter.d("MENU : ATTACHMENT_CONTACT");
				Intent vCardIntent = new Intent(ChatListActivity.this, VCardListActivity.class);
				startActivityForResult(vCardIntent, REQ_VCARD);
				break;
			case MENU_ATTACHMENT_SCHEDULE:
				MTalkLogWriter.d("MENU : ATTACHMENT_SCHEDULE");
				Intent vCalendarIntent = new Intent(ChatListActivity.this, VCalendarListActivity.class);
				startActivityForResult(vCalendarIntent, REQ_VCALENDAR);
				break;
			case MENU_ATTACHMENT_VOICE:
				MTalkLogWriter.d("MENU : ATTACHMENT_VOICE");
				Intent voiceIntent = new Intent(ChatListActivity.this, AudioRecordActivity.class);
				startActivityForResult(voiceIntent, REQ_VOICE);
				break;
			case MENU_ATTACHMENT_GIFT:
				MTalkLogWriter.d("MENU : ATTACHMENT_GIFT");
				break;
			default:
				MTalkLogWriter.d("MENU_DEFAULT : !TODO - MUST ITEM ADD (" + tag + ")");
				break;
		}
		return true;
	}
	
	protected void requestCamera() {
		/* 자체 구현된 카메라 액티비티에 촬영 요청
		Intent cameraIntent = new Intent(ChatListActivity.this, CameraActivity.class);
		startActivityForResult(cameraIntent, REQ_IMAGE_EDIT);
		*/
		
		// 인텐트로 기본 앱 등 다른 앱에 촬영 요청(설정 요구하지 않음)
		Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		startActivityForResult(cameraIntent, REQ_IMAGE_EDIT);
	}
	
	protected void requestVideoRecord() {
		/*	자체 구현된 캠코더 액티비티에 촬영 요청
		Intent voiceRecordIntent = new Intent(ChatListActivity.this, VideoRecordActivity.class);
		startActivityForResult(voiceRecordIntent, REQ_VIDEO_EDIT);
		*/
		
		/*	인텐트로 기본 앱 등 다른 앱에 촬영 요청(자체 설정 요구)
		// 파일 경로 생성
		try {
			String state = android.os.Environment.getExternalStorageState();
		    if(!state.equals(android.os.Environment.MEDIA_MOUNTED))  {
		        throw new IOException("SD Card is not mounted.  It is " + state + ".");
		    }
		} catch (IOException e) {
			MTalkLogWriter.e(e);
			return;
		}
	    
		String fileName = "mnTalkVideo_" + (new SimpleDateFormat("yyyyMMdd_HHmmssSSSZ").format(new Date())) + ".3gp";
		String path = MTalkConstant.MTALK_PATH + "/video/";
		File directory = new File(path);
		if(!directory.exists()){
			directory.mkdirs();
		}
		if (!directory.exists() && !directory.mkdirs()) {
			try {
				throw new IOException("Path to file could not be created.");
			} catch (IOException e) {
				MTalkLogWriter.e(e);
			}
		}
		path += fileName;
		// 만들어진 경로에 비디오 촬영 요청
		ContentValues values = new ContentValues();
		values.put(MediaStore.Video.Media.TITLE, fileName);
		values.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis());
		values.put(MediaStore.Video.Media.MIME_TYPE, "video/3gpp");
		values.put(MediaStore.Video.Media.DATA, path);
		Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
		intent.putExtra(MediaStore.EXTRA_OUTPUT, getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values));
		startActivityForResult(intent, REQ_VIDEO_EDIT);
		*/
		
		// 인텐트로 기본 앱 등 다른 앱에 촬영 요청(설정 요구하지 않음)
		Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
		startActivityForResult(intent, REQ_VIDEO_EDIT);
	}
	
	private ArrayList<DialogListItem> getMenuList(){
		ArrayList<DialogListItem> item = new ArrayList<DialogListItem>();
		// 공통 다이얼 로그 아이템
		item.add(new DialogListItem(this.getResources(), 
				R.string.attachment_image_name, 
				R.drawable.icon_sphotolibrary, 
				MENU_ATTACHMENT_IMAGE));
		item.add(new DialogListItem(this.getResources(), 
				R.string.attachment_video_name, 
				R.drawable.icon_camera, 
				MENU_ATTACHMENT_VIDEO));
		item.add(new DialogListItem(this.getResources(), 
				R.string.attachment_scribble_name, 
				R.drawable.icon_scribble, 
				MENU_ATTACHMENT_SCRIBBLE));
		item.add(new DialogListItem(this.getResources(), 
				R.string.attachment_geotag_name, 
				R.drawable.icon_location, 
				MENU_ATTACHMENT_GEOTAG));
		item.add(new DialogListItem(this.getResources(), 
				R.string.attachment_vcard_name, 
				R.drawable.icon_contact, 
				MENU_ATTACHMENT_CONTACT));
		item.add(new DialogListItem(this.getResources(), 
				R.string.attachment_vcalendar_name, 
				R.drawable.icon_schedule, 
				MENU_ATTACHMENT_SCHEDULE));
//		item.add(new DialogListItem(this.getResources(), 
//				R.string.attachment_??_name, 
//				R.drawable.icon_??, 
//				MENU_ATTACHMENT_VOICE));
//		item.add(new DialogListItem(this.getResources(), 
//				R.string.attachment_??_name, 
//				R.drawable.icon_??, 
//				MENU_ATTACHMENT_GIFT));
		return item;
	}	
	/**
	 * "+" BUTTON
	 * @param view
	 */
//	AlertDialog alertDialog = null;
	public void onMenuClick(View view){
		showDialogMenu();
	}

	/**
	 * 안드로이드 버전 버그에 대응하기 위한 구현.<br>
	 * <br>
	 * onActivityResult() 의 작업을 지연시키기 위해 일시적으로 보존하는 인자 세트.
	 * onActivityResult() -> onResume() 순서로 호출되는데, onResume() 전에는 커서 관리자가 죽어 있다.
	 * 따라서 onActivityResult() 내부에서의 커서 작업은 불가능하다.<br>
	 * <br>
	 * 그러므로 onActivityResult()에서는 인자 세트를 저장만 해 두고,
	 * onResume()의 말미에서 그 인자 세트에 대한 작업을 진행해줘야 한다.
	 * 또한 작업의 진행 후에는 저장했던 인자 세트에 다시 접근하는 일이 없도록 즉시 폐기해야 한다.
	 * @author Arngard
	 */
	class ActivityResult {

		int requestCode;
		int resultCode;
		Intent intent;

		public ActivityResult(int requestCode, int resultCode, Intent intent) {
			super();
			this.requestCode = requestCode;
			this.resultCode = resultCode;
			this.intent = intent;
		}
	}

	/**
	 * onActivityResult() 는 이 인자 세트를 세팅한 후 즉시 종료해야 한다.
	 * onResume() 마지막에서는 이 정보를 이용하여 작업을 진행한 후, 즉시 인자 세트를 폐기한다.
	 */
	ActivityResult mActivityResult = null;

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
		super.onActivityResult(requestCode, resultCode, intent);
		mActivityResult = new ActivityResult(requestCode, resultCode, intent);
	}

	/**
	 * onActivityResult() 에서 하고자 하는 작업을 이 함수에 구현한다.
	 * @param requestCode onActivityResult()에서 저장해뒀던 내용
	 * @param resultCode 위와 같음
	 * @param intent 위와 같음
	 * @see ActivityResult
	 */
	protected void handleActivityResult(int requestCode, int resultCode, Intent intent) {
		if (resultCode != Activity.RESULT_OK) {
			Toast.makeText(this, "Fail to attach", Toast.LENGTH_SHORT);
			return;
		}

		Uri targetUri = null;	// 전송할 대상의 클라이언트측 주소
		UUID clientMsgUuid = UUID.randomUUID();
		switch (requestCode) {
		case REQ_IMAGE_EDIT:
		case REQ_IMAGE_ALBUM:
		case REQ_SCRIBBLE:
			System.gc();
			if (intent == null || intent.getData() == null)
				return;
			targetUri = intent.getData();
			mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.setFileSendMessage(mClientViewUuidMsb, mClientViewUuidLsb, mViewUuidMsg, targetUri, Common.FT_IMG, clientMsgUuid);
			mUiController.sendFile(GpbSupport.makeUuid(mClientViewUuidMsb, mClientViewUuidLsb), null, targetUri, Common.FT_IMG, clientMsgUuid);
			break;
		case REQ_VIDEO_EDIT:
		case REQ_VIDEO_ALBUM:
			System.gc();
			if (intent == null || intent.getData() == null)
				return;
			targetUri = intent.getData();
			mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.setFileSendMessage(mClientViewUuidMsb, mClientViewUuidLsb, mViewUuidMsg, targetUri, Common.FT_VIDEO, clientMsgUuid);
			mUiController.sendFile(GpbSupport.makeUuid(mClientViewUuidMsb, mClientViewUuidLsb), null, targetUri, Common.FT_VIDEO, clientMsgUuid);
			break;
		case REQ_GEOTAG:
			if (intent == null || intent.getExtras() == null)
				return;
			String geotag = intent.getExtras().getString(GeotagActivity.INTENT_GEOTAG_DATA);
			String geotagName = mContext.getString(R.string.attachment_geotag_name);
			mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.sendAttachment(GpbSupport.makeUuid(mClientViewUuidMsb, mClientViewUuidLsb), mViewUuidMsg, geotag, geotagName, MessageProperty.GEOTAG, clientMsgUuid);
			break;
		case REQ_VCARD:
			if (intent == null || intent.getExtras() == null)
				return;
			String vCardFileName = intent.getExtras().getString(VCardListActivity.INTENT_VCARD_FILE_NAME);
			String vCardContent = intent.getExtras().getString(VCardListActivity.INTENT_VCARD_CONTENT);
			mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.sendAttachment(GpbSupport.makeUuid(mClientViewUuidMsb, mClientViewUuidLsb), mViewUuidMsg, vCardContent, vCardFileName, MessageProperty.CONTACT, clientMsgUuid);
			break;
		case REQ_VCALENDAR:
			if (intent == null || intent.getExtras() == null)
				return;
			String vCalendarContent = intent.getExtras().getString(VCalendarListActivity.INTENT_VCALENDAR_CONTENT);
			String vCalendarFileName = intent.getExtras().getString(VCalendarListActivity.INTENT_VCALENDAR_FILE_NAME);
			mViewUuidMsg = InboxDatabaseHelper.getViewUUID(this, mClientViewUuidMsb, mClientViewUuidLsb);
			mUiController.sendAttachment(GpbSupport.makeUuid(mClientViewUuidMsb, mClientViewUuidLsb), mViewUuidMsg, vCalendarContent, vCalendarFileName, MessageProperty.CALENDAR, clientMsgUuid);
			break;
		case REQ_VOICE:
			// hidden on version 2.0
			if (intent == null || intent.getData() == null)
				return;
			targetUri = intent.getData();
			// TODO URI가 가리키는 대상을 전송. 대용량일 가능성이 있음.
			/*{	// 재생 테스트
				Intent showVoice = new Intent(ChatListActivity.this, AudioPlayActivity.class);
				showVoice.setData(targetUri);
				startActivity(showVoice);
			}*/
			break;
		case REQ_GIFT:
			// hidden on version 2.0
			// TODO
			break;
		case REQ_ADDMEMBER:
			if (intent == null)
				return;
			ArrayList<BuddyUUIDItem> list = intent.getParcelableArrayListExtra(INVITE_PERSON);
			if(list == null) return;
			AddMembersReq addMembersReq = new AddMembersReq();
			addMembersReq.setViewUuid(InboxDatabaseHelper.getViewUUID(mContext, mClientViewUuidMsb, mClientViewUuidLsb));
			for(BuddyUUIDItem item : list){
				addMembersReq.addReceiverInfo(new UserBasicInfo().setUserUuid(GpbSupport.makeUuidMsg(item.msb, item.lsb))
						   							   .setDisplayName(item.name));
			}
			mUiController.addMember(addMembersReq);
			// TODO ADDMEMBER
			
			break;
		case REQ_CODE_VOICE_RECOGNITION:
			ArrayList<String> matches = intent.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
			editText.setText(editText.getText() + matches.get(0));
			break;
		default:
			// unknown requestCode
			break;
		}
	}

	public void onEditClick(View view){
		//InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		//SoftKeyboardResults softKeyboardResult = new SoftKeyboardResults(editText.getHandler());
		//mgr.showSoftInput(editText, InputMethodManager.SHOW_IMPLICIT, softKeyboardResult);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(0, MENU_INPUT_VOICE, 10, mContext.getString(R.string.chat_menu_input_voice));
		menu.add(0, MENU_ADD_MEMBER, 20, mContext.getString(R.string.chat_menu_invite_friend));
		menu.add(0, MENU_ATTACHMENT, 30, mContext.getString(R.string.chat_menu_attachment));
		menu.add(0, MENU_SEND_EMAIL, 40, mContext.getString(R.string.chat_menu_send_email));
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch(item.getItemId()){
		case MENU_INPUT_VOICE:
			startVoiceRecognitionActivity();
			break;
		case MENU_ADD_MEMBER :
			if(mEnable != ViewTable.EnableType.LEAVE.ordinal()){
				startActivityForResult(new Intent(mContext, SelectBuddy.class)
							.putExtra("msb", mClientViewUuidMsb)
							.putExtra("lsb", mClientViewUuidLsb)
							, REQ_ADDMEMBER);
//				ReceiverList list = InboxDatabaseHelper.getReceiverList(this, mClientViewUuidMsb, mClientViewUuidLsb);
//				mUiController.addMemebers(mClientViewUuidMsb, mClientViewUuidLsb);
			}
			break;
		case MENU_ATTACHMENT:
			showDialogMenu();
			break;
		case MENU_SEND_EMAIL:
			mUiController.backupHistoryMessage(new UUID(mClientViewUuidMsb, mClientViewUuidLsb));
			break;
		}
		return super.onMenuItemSelected(featureId, item);
	}
	/**
	 * Fire an intent to start the speech recognition activity.
	 */
	private void startVoiceRecognitionActivity() {
		Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
		intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
		intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.chat_input_voice));
		startActivityForResult(intent, REQ_CODE_VOICE_RECOGNITION);
	}
	
	private void setInputSuggestions(int orientation){
		switch(orientation){
			case Configuration.ORIENTATION_LANDSCAPE:
				editText.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_MULTI_LINE|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
				break;
			case Configuration.ORIENTATION_PORTRAIT:
				editText.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_MULTI_LINE);
				break;
			case Configuration.ORIENTATION_UNDEFINED:
			case Configuration.ORIENTATION_SQUARE:
			default:
				break;
		}
	}
	/*private void setBackGround(int orientation){
		if(GlobalPreferences.getBgImageUriString() != null){
			Bitmap bm;
			Bitmap resizedBitmap;
			BitmapDrawable bmd;
			bgImage.setVisibility(View.VISIBLE);
			String bgPath = GlobalPreferences.getBgImageUriString();
			try {
				Matrix matrix = new Matrix();
				bm = MediaStore.Images.Media.getBitmap(getContentResolver(), Uri.parse(bgPath));
				float scaleWidth = ((float) 480) / bm.getWidth(); 
		        float scaleHeight = ((float) 800) / bm.getHeight(); 
				switch(orientation){
					case Configuration.ORIENTATION_LANDSCAPE:
						Log.i("ATOM", "BB  : " + scaleWidth + ", " + scaleHeight);
						Log.i("ATOM", "BB  : " + bm.getWidth() + ", " + bm.getHeight());
						matrix.postRotate(270);
						matrix.postScale(scaleWidth, scaleHeight);
//						matrix.setScale(2.0f, 2.0f);
						resizedBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
						bmd = new BitmapDrawable(resizedBitmap); 
						bgImage.setScaleType(ImageView.ScaleType.FIT_XY);
						bgImage.setImageDrawable(bmd);
						break;
					case Configuration.ORIENTATION_PORTRAIT:
						Log.i("ATOM", "CC : " + scaleWidth + ", " + scaleHeight);
						Log.i("ATOM", "CC : " + bm.getWidth() + ", " + bm.getHeight());
//						BitmapFactory.Options bo = new BitmapFactory.Options();
//						bo.in
						matrix.postRotate(0);
						matrix.postScale(scaleWidth, scaleHeight);
//						Bitmap.createScaledBitmapC
						resizedBitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
						bmd = new BitmapDrawable(resizedBitmap);
						bgImage.setScaleType(ImageView.ScaleType.FIT_XY);
						bgImage.setImageDrawable(bmd);
						break;
					case Configuration.ORIENTATION_UNDEFINED:
					case Configuration.ORIENTATION_SQUARE:
						break;
				}
			} catch (FileNotFoundException e) {
				MTalkLogWriter.e(e);
			} catch (IOException e) {
				MTalkLogWriter.e(e);
			}
		}else if(GlobalPreferences.getBgColor() != -1){
			bgImage.setVisibility(View.GONE);
			findViewById(R.id.rLayoutChatParent).setBackgroundColor(GlobalPreferences.getBgColor());
		}else{
			bgImage.setVisibility(View.GONE);
			findViewById(R.id.rLayoutChatParent).setBackgroundColor(getResources().getColor(R.color.chat_background_default));
		}
	}*/

	@Override
	public boolean dispatchKeyEvent(KeyEvent event) {
		switch (event.getKeyCode()) {
		case KeyEvent.KEYCODE_BACK:
			switch (event.getAction()) {
			case KeyEvent.ACTION_DOWN:
				if (emoticonPopupWindow != null && emoticonPopupWindow.isShowing()) {
					return true;
				}
			case KeyEvent.ACTION_UP:
				if (emoticonPopupWindow != null && emoticonPopupWindow.isShowing()) {
					emoticonPopupWindow.dismiss();
					return true;
				}
				break;
			}
			break;
		}
		return super.dispatchKeyEvent(event);
	}

}